(use-modules
 (srfi srfi-9) ;record tipes
 (srfi srfi-1) ;manipular listas
; (srfi srfi-18) 
 )

(load "scpf.scm")

(define-record-type filosofo
  (make-filosofo garf-esq garf-dir)
  filosofo?
  (garf-esq get-garf-esq set-garf-esq!)
  (garf-dir get-garf-dir set-garf-dir!))

(define comer ;pega garfo, come, devolve, repete recursivamente
  (lambda (filo)
    (mutex-lock! (get-garf-esq filo))
    (mutex-lock! (get-garf-dir filo))
    (display filo) (display "is nomnomnoming\n")
    (mutex-unlock! (get-garf-esq filo))
    (mutex-unlock! (get-garf-dir filo))
    (comer filo)))

(define (prepara-mesa n-talheres); cria os talheres(mutexes) e os coloca na mesa(lista)
  (letrec
      ((prepara-mesa-aux
       (lambda (n-talheres mesa) ;1 talher por convidado
	 (if (= n-talheres 0)
	     mesa
	     (prepara-mesa-aux
	      (- n-talheres 1)
	      (cons (make-mutex) mesa))))))
    (prepara-mesa-aux n-talheres '() )))

(define (senta-filosofos n-filosofos mesa) ;atribui os talheres(mutexes) aos filosofos
  (letrec ((senta-filosofos-aux
      (lambda (n-filosofos cadeiras mesa iter)
	(cond
	  ((= n-filosofos 0)
	    cadeiras)
	  ((= n-filosofos 1)
	   (cons (make-filosofo (last mesa) (car mesa)) cadeiras))
	  (else
	   (senta-filosofos-aux
	    (- n-filosofos 1)
	    (cons
	     (make-filosofo (list-ref mesa iter) (list-ref mesa (+ iter 1)))
	     cadeiras)
	   mesa
	   (+ iter 1)))))))
      (senta-filosofos-aux n-filosofos '() mesa 0)))

(define filos (senta-filosofos 3 (prepara-mesa 3)));pequena mesa para 3, o suficiente para segmentation fault no nosso humilde restaurante

;cada cria uma thread para cada filósofo e a inicia. não me preocupei com joins
(map thread-start!
     (map
      (lambda (filo)
	(make-thread (lambda ()
		       (comer filo))))
      filos))